﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Runtime.InteropServices;

namespace Gmantis.Controls
{
    [StructLayout(LayoutKind.Sequential)]
    public struct HslColor
    {
        private const float half = 0.5f;
        private const float oneThird = 0.3333333f;
        private const float twoThirds = 0.6666667f;
        private const float oneSixth = 0.1666667f;
        private const float one255th = 0.003921569f;
        private float _h;
        private float _s;
        private float _l;
        private byte _a;

        public HslColor(float h, float s, float l)
        {
            this._h = h;
            this._s = s;
            this._l = l;
            this._a = 0xff;
        }

        public HslColor(byte a, float h, float s, float l)
        {
            this._h = h;
            this._s = s;
            this._l = l;
            this._a = a;
        }

        public HslColor(Color rgbColor)
        {
            byte r = rgbColor.R;
            byte g = rgbColor.G;
            byte b = rgbColor.B;
            float num4 = r * 0.003921569f;
            float num5 = g * 0.003921569f;
            float num6 = b * 0.003921569f;
            this._a = rgbColor.A;
            byte num7 = (r < g) ? ((r < b) ? r : b) : ((g < b) ? g : b);
            byte num8 = (r > g) ? ((r > b) ? r : b) : ((g > b) ? g : b);
            float num9 = num7 * 0.003921569f;
            float num10 = num8 * 0.003921569f;
            this._h = 0f;
            if (num8 != num7)
            {
                if (num8 == r)
                {
                    this._h = (num5 - num6) / (num10 - num9);
                }
                else if (num8 == g)
                {
                    this._h = 2f + ((num6 - num4) / (num10 - num9));
                }
                else if (num8 == b)
                {
                    this._h = 4f + ((num4 - num5) / (num10 - num9));
                }
            }
            if (this._h < 0f)
            {
                this._h += 6f;
            }
            this._h *= 0.1666667f;
            this._l = (num9 + num10) * 0.5f;
            if (num8 == num7)
            {
                this._s = 0f;
            }
            else if (this._l <= 0.5f)
            {
                this._s = (num10 - num9) / (num10 + num9);
            }
            else
            {
                this._s = (num10 - num9) / ((2f - num10) - num9);
            }
        }

        public float Hue
        {
            get
            {
                return this._h;
            }
            set
            {
                this._h = Math.Max(0f, Math.Min(1f, value));
            }
        }

        public float Saturation
        {
            get
            {
                return this._s;
            }
            set
            {
                this._s = Math.Max(0f, Math.Min(1f, value));
            }
        }
        public float Luminance
        {
            get
            {
                return this._l;
            }
            set
            {
                this._l = Math.Max(0f, Math.Min(1f, value));
            }
        }
        public byte Alpha
        {
            get
            {
                return this._a;
            }
            set
            {
                this._a = value;
            }
        }

        public HslColor Lighter(int percent)
        {
            float l = this._l;
            if (percent < 0)
            {
                l += (l * percent) * 0.01f;
            }
            else
            {
                l += ((1f - l) * percent) * 0.01f;
            }
            return new HslColor(this._h, this._s, l);
        }

        public HslColor Darker(int percent)
        {
            float l = this._l;
            if (percent < 0)
            {
                l -= ((1f - l) * percent) * 0.01f;
            }
            else
            {
                l -= (l * percent) * 0.01f;
            }
            return new HslColor(this._h, this._s, l);
        }

        internal HslColor ModifyLuminance(float percent)
        {
            if ((percent < -1f) || (percent > 1f))
            {
                throw new ArgumentException("The percent parameter must be between -1 and 1");
            }
            float l = this._l;
            if (percent > 0f)
            {
                l += (1f - l) * percent;
            }
            else
            {
                l += l * percent;
            }
            return new HslColor(this._a, this._h, this._s, l);
        }

        internal HslColor ModifySaturation(float percent)
        {
            if ((percent < -1f) || (percent > 1f))
            {
                throw new ArgumentException("The percent parameter must be between -1 and 1");
            }
            float s = this._s;
            if (percent > 0f)
            {
                s += (1f - s) * percent;
            }
            else
            {
                s += s * percent;
            }
            return new HslColor(this._a, this._h, s, this._l);
        }

        internal HslColor ModifyHue(float percent)
        {
            if ((percent < -1f) || (percent > 1f))
            {
                throw new ArgumentException("The percent parameter must be between -1 and 1");
            }
            float h = this._h;
            if (percent > 0f)
            {
                h += (1f - h) * percent;
            }
            else
            {
                h += h * percent;
            }
            return new HslColor(this._a, h, this._s, this._l);
        }

        public Color ToColor()
        {
            return this.ToColor(this.Alpha);
        }

        public Color ToColor(byte alpha)
        {
            float num = (this._l < 0.5f) ? (this._l * (this._s + 1f)) : ((this._l + this._s) - (this._l * this._s));
            float num2 = (this._l + this._l) - num;
            float num3 = this._h + 0.3333333f;
            if (num3 > 1f)
            {
                num3--;
            }
            float num4 = this._h;
            float num5 = this._h - 0.3333333f;
            if (num5 < 0f)
            {
                num5++;
            }
            if (num3 < 0.1666667f)
            {
                num3 = (((num - num2) * num3) * 6f) + num2;
            }
            else if (num3 < 0.5f)
            {
                num3 = num;
            }
            else if (num3 < 0.6666667f)
            {
                num3 = (((num - num2) * (0.6666667f - num3)) * 6f) + num2;
            }
            else
            {
                num3 = num2;
            }
            if (num4 < 0.1666667f)
            {
                num4 = (((num - num2) * num4) * 6f) + num2;
            }
            else if (num4 < 0.5f)
            {
                num4 = num;
            }
            else if (num4 < 0.6666667f)
            {
                num4 = (((num - num2) * (0.6666667f - num4)) * 6f) + num2;
            }
            else
            {
                num4 = num2;
            }
            if (num5 < 0.1666667f)
            {
                num5 = (((num - num2) * num5) * 6f) + num2;
            }
            else if (num5 < 0.5f)
            {
                num5 = num;
            }
            else if (num5 < 0.6666667f)
            {
                num5 = (((num - num2) * (0.6666667f - num5)) * 6f) + num2;
            }
            else
            {
                num5 = num2;
            }
            return Color.FromArgb(alpha, Convert.ToByte((float)(num3 * 255f)), Convert.ToByte((float)(num4 * 255f)), Convert.ToByte((float)(num5 * 255f)));
        }

        public static Color ToColor(float h, float s, float l)
        {
            HslColor color = new HslColor(h, s, l);
            return color.ToColor(0xff);
        }
    }
}
